package com.base.component.aws.s3;

import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.amazonaws.HttpMethod;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.auth.BasicSessionCredentials;
import com.amazonaws.client.builder.AwsClientBuilder.EndpointConfiguration;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.securitytoken.AWSSecurityTokenService;
import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder;
import com.amazonaws.services.securitytoken.model.Credentials;
import com.amazonaws.services.securitytoken.model.GetSessionTokenRequest;
import com.amazonaws.services.securitytoken.model.GetSessionTokenResult;
import com.gitee.magic.core.utils.StringUtils;
import com.gitee.magic.framework.head.utils.TimeUtils;

/**
 * @author start 
 */
@Service
public class S3Service {

	@Value("${aws.s3.endPoint:https://s3.amazonaws.com}")
	private String endPoint;
	@Value("${aws.s3.accessid}")
	private String accessId;
	@Value("${aws.s3.accesskey}")
	private String accessKey;
	@Value("${aws.s3.expirationMinute:10080}")
	public Integer expirationMinute;
	@Value("${aws.s3.sts.expirationMinute:900}")
	public Integer stsExpirationMinute;
	
	public AmazonS3 getAmazonS3(String regionName) {
		BasicAWSCredentials credentials = new BasicAWSCredentials(accessId, accessKey);
		if(StringUtils.isEmpty(endPoint)) {
			return AmazonS3ClientBuilder.standard()
	        		.withCredentials(new AWSStaticCredentialsProvider(credentials))
					.withRegion(regionName)
	                .build();
		}
		return AmazonS3ClientBuilder.standard()
        		.withCredentials(new AWSStaticCredentialsProvider(credentials))
        		.withEndpointConfiguration(new EndpointConfiguration(endPoint,regionName))
                .build();
	}
	
	public AmazonS3 getAmazonS3(String regionName,String awsAccessKey, String awsSecretKey, String sessionToken) {
		BasicSessionCredentials sessionCredentials = new BasicSessionCredentials(
				awsAccessKey,awsSecretKey,sessionToken);
		return AmazonS3ClientBuilder.standard()
        		.withCredentials(new AWSStaticCredentialsProvider(sessionCredentials))
        		.withEndpointConfiguration(new EndpointConfiguration(endPoint,regionName))
                .build();
	}
	
	public AWSSecurityTokenService getAWSSecurityTokenService(String regionName) {
		BasicAWSCredentials credentials = new BasicAWSCredentials(accessId, accessKey);
		return AWSSecurityTokenServiceClientBuilder.standard()
				.withCredentials(new AWSStaticCredentialsProvider(credentials))
				.withRegion(regionName)
				.build();
	}
	
	public boolean doesObjectExist(String regionName,String bucketName,String key) {
		AmazonS3 s3 = getAmazonS3(regionName);
		return s3.doesObjectExist(bucketName, key);
	}
	
	public void putObject(String regionName,String bucketName, String key,File file) {
		AmazonS3 s3 = getAmazonS3(regionName);
		s3.putObject(new PutObjectRequest(bucketName, key, file));
	}
	
	public void putObject(String regionName,String bucketName,String key,InputStream inputStream) {
		putObject(regionName,bucketName, key, inputStream,null);
	}
	
	public void putObject(String regionName,String bucketName,String key,InputStream inputStream,ObjectMetadata metadata) {
		AmazonS3 s3 = getAmazonS3(regionName);
		s3.putObject(bucketName, key, inputStream,metadata);
	}
	
	public void setObjectAcl(String regionName,String bucketName, String key) {
		AmazonS3 s3 = getAmazonS3(regionName);
		s3.setObjectAcl(bucketName, key, CannedAccessControlList.PublicRead);
	}
	
	public void deleteObject(String regionName,String bucketName, String key) {
		AmazonS3 s3 = getAmazonS3(regionName);
		s3.deleteObject(bucketName, key);
	}
	
	public void getObject(String regionName,String bucketName, String key,File file) {
		AmazonS3 s3 = getAmazonS3(regionName);
		s3.getObject(new GetObjectRequest(bucketName,key), file);
	}
	
	public InputStream getObjectInputStream(String regionName,String bucketName, String key) {
		AmazonS3 s3 = getAmazonS3(regionName);
		S3Object obj=s3.getObject(new GetObjectRequest(bucketName,key));
		return obj.getObjectContent().getDelegateStream();
	}

	/**
	 * 生成下载地址
	 * @param endPoint
	 * @param regionName
	 * @param bucketName
	 * @param key
	 * @param isExpiration
	 * @return
	 */
	public String getUrl(String regionName,String bucketName,String key,Boolean isExpiration) {
		return getUrl(regionName,bucketName,key,isExpiration,HttpMethod.GET);
	}
	
	public String getUrl(String regionName,String bucketName,String key,Boolean isExpiration,HttpMethod method) {
		if(isExpiration) {
			Date expiration =TimeUtils.getMinute(expirationMinute);
			GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(bucketName, key);
			urlRequest.setMethod(method);
			urlRequest.setExpiration(expiration);
			URL url = getAmazonS3(regionName).generatePresignedUrl(urlRequest);
			return url.toString();
		}else {
			URL url = getAmazonS3(regionName).getUrl(bucketName, key);
			return url.toString();
		}
	}
	
	/**
	 * STS临时授权用BasicSessionCredentials封装授权
	 * @param endPoint
	 * @param regionName
	 * @return
	 */
	public Credentials getStsCredentials(String regionName) {
		AWSSecurityTokenService client = getAWSSecurityTokenService(regionName);
		GetSessionTokenRequest sessionTokenRequest = new GetSessionTokenRequest();
		sessionTokenRequest.setDurationSeconds(stsExpirationMinute);
		GetSessionTokenResult sessionTokenResult =
				client.getSessionToken(sessionTokenRequest);
		Credentials sessionCreds = sessionTokenResult.getCredentials();
		return sessionCreds;
	}
	
	public static void main(String[] args) {
		S3Service s=new S3Service();
		s.accessId="";
		s.accessKey="";
		s.endPoint="";
		s.expirationMinute=10080;
		s.stsExpirationMinute=900;
		System.out.println(s.getUrl(
				"us-west-1", 
				"aimate-pn-private", 
				"aimate/video/chat/5565add0f17df91468c749fb81881dcc.mp4", false));
	}
	
}
